home *** CD-ROM | disk | FTP | other *** search
/ Joystick Magazine 1996 July & August / cd joy 73 No15.iso / pc / wing / palanim.c_ / palanim.c
C/C++ Source or Header  |  1994-12-08  |  32KB  |  1,017 lines

  1. /**************************************************************************
  2.  
  3.     PALANIM.C - A palette animation demo for WinG
  4.  
  5.  **************************************************************************/
  6. /**************************************************************************
  7.  
  8.     (C) Copyright 1994 Microsoft Corp.  All rights reserved.
  9.  
  10.     You have a royalty-free right to use, modify, reproduce and 
  11.     distribute the Sample Files (and/or any modified version) in 
  12.     any way you find useful, provided that you agree that 
  13.     Microsoft has no warranty obligations or liability for any 
  14.     Sample Application Files which are modified. 
  15.  
  16.  **************************************************************************/
  17.  
  18. #include <windows.h>
  19. #include <commdlg.h>
  20. #include <wing.h>
  21.  
  22. #include "palanim.h"
  23. #include "..\utils\utils.h"
  24.  
  25. /*----------------------------------------------------------------------------*\
  26. |                                                                              |
  27. |   g l o b a l   v a r i a b l e s                                            |
  28. |                                                                              |
  29. \*----------------------------------------------------------------------------*/
  30. static  char       szAppName[]="WinG Palette Animation App";
  31.  
  32. static  HINSTANCE  hInstApp;
  33. static  HWND       hwndApp;
  34. static  HPALETTE   hpalApp;
  35. static  BOOL       fAppActive;
  36.  
  37. static  HDC        hdcOffscreen;
  38. void far *         gpBits;
  39.  
  40. struct {
  41.   BITMAPINFOHEADER InfoHeader;
  42.   RGBQUAD ColorTable[256];
  43. } gInfo;
  44.  
  45. int  fAnimatePalette = 0;    // Don't animate
  46. int  fIncludeStatic = 0;     // Use the static color entries
  47. enum {Red, Green, Blue}  gWashColor = Red;
  48.  
  49. PALETTEENTRY  aPalette[256];
  50.  
  51. extern HBITMAP  ghBitmapMonochrome;
  52.  
  53. #ifdef WIN32
  54.     #define _export
  55. #endif
  56.  
  57. //*** Setting up SYSPAL_NOSTATIC
  58.  
  59. #define NumSysColors (sizeof(SysPalIndex)/sizeof(SysPalIndex[1]))
  60. #define rgbBlack RGB(0,0,0)
  61. #define rgbWhite RGB(255,255,255)
  62.  
  63. //*** These are the GetSysColor display element identifiers
  64. static int SysPalIndex[] = {
  65.   COLOR_ACTIVEBORDER,
  66.   COLOR_ACTIVECAPTION,
  67.   COLOR_APPWORKSPACE,
  68.   COLOR_BACKGROUND,
  69.   COLOR_BTNFACE,
  70.   COLOR_BTNSHADOW,
  71.   COLOR_BTNTEXT,
  72.   COLOR_CAPTIONTEXT,
  73.   COLOR_GRAYTEXT,
  74.   COLOR_HIGHLIGHT,
  75.   COLOR_HIGHLIGHTTEXT,
  76.   COLOR_INACTIVEBORDER,
  77.  
  78.   COLOR_INACTIVECAPTION,
  79.   COLOR_MENU,
  80.   COLOR_MENUTEXT,
  81.   COLOR_SCROLLBAR,
  82.   COLOR_WINDOW,
  83.   COLOR_WINDOWFRAME,
  84.   COLOR_WINDOWTEXT
  85. };
  86.  
  87. //*** This array translates the display elements to black and white
  88. static COLORREF MonoColors[] = {
  89.   rgbBlack,
  90.   rgbWhite,
  91.   rgbWhite,
  92.   rgbWhite,
  93.   rgbWhite,
  94.   rgbBlack,
  95.   rgbBlack,
  96.   rgbBlack,
  97.   rgbBlack,
  98.   rgbBlack,
  99.   rgbWhite,
  100.   rgbWhite,
  101.   rgbWhite,
  102.   rgbWhite,
  103.   rgbBlack,
  104.   rgbWhite,
  105.   rgbWhite,
  106.   rgbBlack,
  107.  
  108.   rgbBlack
  109. };
  110.  
  111. //*** This array holds the old color mapping so we can restore them
  112. static COLORREF OldColors[NumSysColors];
  113.  
  114.  
  115.  
  116. /*----------------------------------------------------------------------------*\
  117. |                                                                              |
  118. |   f u n c t i o n   d e f i n i t i o n s                                    |
  119. |                                                                              |
  120. \*----------------------------------------------------------------------------*/
  121.  
  122. LONG FAR PASCAL _export AppWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam);
  123. int  ErrMsg (LPSTR sz,...);
  124. LONG AppCommand (HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam);
  125.  
  126. void AppExit(void);
  127. BOOL AppIdle(void);
  128.  
  129. /***************************************************************************
  130.   Internal functions for the animation
  131. */
  132.  
  133. void  CreateWashPalette(void);
  134. void  DibCreateWash(BITMAPINFOHEADER far *Info, void far *pBits);
  135. void  DibHorizontalLine(BITMAPINFOHEADER far *Info, void far *pBits,
  136.                         int y, char unsigned color);
  137.  
  138. /***************************************************************************
  139.   Sample functions from wing.hlp
  140. */
  141.  
  142. HDC   Create100x100WinGDC(void);
  143. void  Destroy100x100WinGDC(HDC hWinGDC);
  144.  
  145. void  AppActivate(BOOL fActive);
  146.  
  147. HPALETTE CreateIdentityPalette(RGBQUAD aRGB[], int nColors);
  148.  
  149. /*----------------------------------------------------------------------------*\
  150. |   AppAbout( hDlg, uiMessage, wParam, lParam )                                |
  151. |                                                                              |
  152. |   Description:                                                               |
  153. |       This function handles messages belonging to the "About" dialog box.    |
  154. |       The only message that it looks for is WM_COMMAND, indicating the use   |
  155. |       has pressed the "OK" button.  When this happens, it takes down         |
  156. |       the dialog box.                                                        |
  157. |                                                                              |
  158. |   Arguments:                                                                 |
  159. |       hDlg            window handle of about dialog window                   |
  160. |       uiMessage       message number                                         |
  161. |       wParam          message-dependent                                      |
  162. |       lParam          message-dependent                                      |
  163. |                                                                              |
  164. |   Returns:                                                                   |
  165. |       TRUE if message has been processed, else FALSE                         |
  166. |                                                                              |
  167. \*----------------------------------------------------------------------------*/
  168. BOOL FAR PASCAL _export AppAbout(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
  169. {
  170.     switch (msg)
  171.     {
  172.         case WM_COMMAND:
  173.             if (LOWORD(wParam) == IDOK)
  174.             {
  175.                 EndDialog(hwnd,TRUE);
  176.             }
  177.             break;
  178.  
  179.         case WM_INITDIALOG:
  180.             return TRUE;
  181.     }
  182.     return FALSE;
  183. }
  184.  
  185. /*----------------------------------------------------------------------------*\
  186. |   AppInit( hInst, hPrev)                                                     |
  187. |                                                                              |
  188. |   Description:                                                               |
  189. |       This is called when the application is first loaded into               |
  190. |       memory.  It performs all initialization that doesn't need to be done   |
  191. |       once per instance.                                                     |
  192. |                                                                              |
  193. |   Arguments:                                                                 |
  194. |       hInstance       instance handle of current instance                    |
  195. |       hPrev           instance handle of previous instance                   |
  196. |                                                                              |
  197. |   Returns:                                                                   |
  198. |       TRUE if successful, FALSE if not                                       |
  199. |                                                                              |
  200. \*----------------------------------------------------------------------------*/
  201. BOOL AppInit(HINSTANCE hInst,HINSTANCE hPrev,int sw,LPSTR szCmdLine)
  202. {
  203.   WNDCLASS  cls;
  204.   int       dx,dy;
  205.   HBITMAP   hbmOffscreen;
  206.   HMENU     hMenu;
  207.   HDC       Screen;
  208.   int         PaletteDevice;
  209.   int         nBitsPixel;         
  210.   int         nPlanes;         
  211.   int       nColorDepth;
  212.       
  213.     /* Save instance handle for DialogBoxes */
  214.     hInstApp = hInst;
  215.  
  216.     /* Refuse to run if this is a non-palettized device */
  217.     Screen = GetDC(0);
  218.  
  219.     if (Screen)
  220.     {
  221.       PaletteDevice = GetDeviceCaps(Screen, RASTERCAPS) & RC_PALETTE;
  222.       nBitsPixel = GetDeviceCaps(Screen, BITSPIXEL);         
  223.       nPlanes = GetDeviceCaps(Screen, PLANES);         
  224.       nColorDepth = nBitsPixel * nPlanes;
  225.       ReleaseDC(0, Screen);
  226.  
  227.       if ((8 != nColorDepth) || (0 == PaletteDevice))
  228.       {
  229.         MessageBox(0,
  230.          "Palette animation requires a palettized display device - change to 256 colors.",
  231.          "Non-palettized Display",
  232.          MB_OK);
  233.         return FALSE;
  234.       }
  235.     }
  236.  
  237. // Clear the System Palette.
  238.     ClearSystemPalette();
  239.  
  240.     if (!hPrev)
  241.     {
  242.         /*
  243.          *  Register a class for the main application window
  244.          */
  245.         cls.hCursor        = LoadCursor(NULL,IDC_ARROW);
  246.         cls.hIcon          = LoadIcon(hInst,"AppIcon");
  247.         cls.lpszMenuName   = "AppMenu";
  248.         cls.lpszClassName  = szAppName;
  249.         cls.hbrBackground  = (HBRUSH)(COLOR_WINDOW + 1);
  250.         cls.hInstance      = hInst;
  251.         cls.style          = CS_BYTEALIGNCLIENT | CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;
  252.         cls.lpfnWndProc    = (WNDPROC)AppWndProc;
  253.         cls.cbWndExtra     = 0;
  254.         cls.cbClsExtra     = 0;
  255.  
  256.         if (!RegisterClass(&cls))
  257.             return FALSE;
  258.     }
  259.  
  260.     dx = GetSystemMetrics (SM_CXSCREEN) / 2;
  261.     dy = GetSystemMetrics (SM_CYSCREEN) / 2;
  262.  
  263.     hwndApp = CreateWindow (szAppName,              // Class name
  264.                             szAppName,              // Caption
  265.                             WS_OVERLAPPEDWINDOW,    // Style bits
  266.                             CW_USEDEFAULT, 0,       // Position
  267.                             dx,dy,                  // Size
  268.                             (HWND)NULL,             // Parent window (no parent)
  269.                             (HMENU)NULL,            // use class menu
  270.                             hInst,                  // handle to window instance
  271.                             (LPSTR)NULL             // no params to pass on
  272.                            );
  273.     ShowWindow(hwndApp,sw);
  274.  
  275.   //*** Create the WinGDC  (actually 256x256)
  276.   hdcOffscreen = Create100x100WinGDC();
  277.  
  278.   //*** Check the menu to reflect initial palette (red)
  279.   hMenu = GetMenu(hwndApp);
  280.   CheckMenuItem(hMenu, MENU_STATIC, fIncludeStatic ? MF_CHECKED : MF_UNCHECKED);
  281.   CheckMenuItem(hMenu, MENU_RED, MF_CHECKED);
  282.   CheckMenuItem(hMenu, MENU_GREEN, MF_UNCHECKED);
  283.   CheckMenuItem(hMenu, MENU_BLUE, MF_UNCHECKED);
  284.  
  285.   //*** Hack to get the offscreen HBITMAP
  286.   hbmOffscreen = (HBITMAP)SelectObject(hdcOffscreen, ghBitmapMonochrome);
  287.   SelectObject(hdcOffscreen, hbmOffscreen);
  288.  
  289.   //*** Initialize the DIB to a wash from top to bottom
  290.   gpBits = WinGGetDIBPointer(hbmOffscreen, (BITMAPINFO far *)&gInfo);
  291.   DibCreateWash(&gInfo.InfoHeader, gpBits);
  292.  
  293.   //*** Reset the color palette
  294.   ClearSystemPalette();
  295.   CreateWashPalette();
  296.  
  297.   return TRUE;
  298. }
  299.  
  300.  
  301. /*----------------------------------------------------------------------------*\
  302. |   AppExit()                                                                  |
  303. |                                                                              |
  304. |   Description:                                                               |
  305. |     App is just about to exit, cleanup.                                      |
  306. |                                                                              |
  307. \*----------------------------------------------------------------------------*/
  308. void AppExit()
  309. {
  310.   if (hdcOffscreen)
  311.     Destroy100x100WinGDC(hdcOffscreen);
  312.  
  313.   if (hpalApp)
  314.     DeleteObject(hpalApp);
  315.  
  316.   //*** Be sure to restore the state on exit!
  317.   if (fIncludeStatic)
  318.     AppActivate(FALSE);
  319. }
  320.  
  321. /*----------------------------------------------------------------------------*\
  322. |   WinMain( hInst, hPrev, lpszCmdLine, cmdShow )                              |
  323. |                                                                              |
  324. |   Description:                                                               |
  325. |       The main procedure for the App.  After initializing, it just goes      |
  326. |       into a message-processing loop until it gets a WM_QUIT message         |
  327. |       (meaning the app was closed).                                          |
  328. |                                                                              |
  329. |   Arguments:                                                                 |
  330. |       hInst           instance handle of this instance of the app            |
  331. |       hPrev           instance handle of previous instance, NULL if first    |
  332. |       szCmdLine       ->null-terminated command line                         |
  333. |       cmdShow         specifies how the window is initially displayed        |
  334. |                                                                              |
  335. |   Returns:                                                                   |
  336. |       The exit code as specified in the WM_QUIT message.                     |
  337. |                                                                              |
  338. \*----------------------------------------------------------------------------*/
  339. int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
  340. {
  341.     MSG     msg;
  342.  
  343.     /* Call initialization procedure */
  344.     if (!AppInit(hInst,hPrev,sw,szCmdLine))
  345.       return FALSE;
  346.  
  347.     /*
  348.      * Polling messages from event queue
  349.      */
  350.     for (;;)
  351.     {
  352.         if (PeekMessage(&msg, NULL, 0, 0,PM_REMOVE))
  353.         {
  354.             if (msg.message == WM_QUIT)
  355.                 break;
  356.  
  357.             TranslateMessage(&msg);
  358.             DispatchMessage(&msg);
  359.         }
  360.         else
  361.         {
  362.             if (AppIdle())
  363.                 WaitMessage();
  364.         }
  365.     }
  366.  
  367.     AppExit();
  368.     return msg.wParam;
  369. }
  370.  
  371. /*----------------------------------------------------------------------------*\
  372. |   AppIdle()                                                                  |
  373. |                                                                              |
  374. |   Description:                                                               |
  375. |     Place to do idle time stuff.                                             |
  376. |                                                                              |
  377. \*----------------------------------------------------------------------------*/
  378. BOOL AppIdle()
  379. {
  380.     if (fAppActive)
  381.     {
  382.         return TRUE;
  383.     }
  384.     else
  385.     {
  386.   //
  387.   // we are a background app.
  388.   //
  389.         return TRUE;      // nothing to do.
  390.     }
  391. }
  392.  
  393. /*----------------------------------------------------------------------------*\
  394. |   AppPaint(hwnd, hdc)                                                        |
  395. |                                                                              |
  396. |   Description:                                                               |
  397. |       The paint function.                                                    |
  398. |                                                                              |
  399. |   Arguments:                                                                 |
  400. |       hwnd             window painting into                                  |
  401. |       hdc              display context to paint to                           |
  402. |                                                                              |
  403. \*----------------------------------------------------------------------------*/
  404. AppPaint (HWND hwnd, HDC hdc)
  405. {
  406.     RECT    rc;
  407.  
  408.     GetClientRect(hwnd,&rc);
  409.  
  410.     SetTextColor(hdc,GetSysColor(COLOR_WINDOWTEXT));
  411.     SetBkColor(hdc,GetSysColor(COLOR_WINDOW));
  412.  
  413.   if (hdcOffscreen)
  414.   {
  415.     int i;
  416.     PALETTEENTRY aPalette[256];
  417.     RGBQUAD aPaletteRGB[256];
  418.  
  419.     //*** BEFORE BLTTING, match the DIB color table to the
  420.     //*** current palette to match the animated palette
  421.     GetPaletteEntries(hpalApp, 0, 256, aPalette);
  422.     //*** Alas, palette entries are r-g-b, rgbquads are b-g-r
  423.     for (i=0; i<256; ++i)
  424.     {
  425.       aPaletteRGB[i].rgbRed = aPalette[i].peRed;
  426.       aPaletteRGB[i].rgbGreen = aPalette[i].peGreen;
  427.       aPaletteRGB[i].rgbBlue = aPalette[i].peBlue;
  428.       aPaletteRGB[i].rgbReserved = 0;
  429.     }
  430.     WinGSetDIBColorTable(hdcOffscreen, 0, 256, aPaletteRGB);
  431.  
  432.     WinGBitBlt(hdc,0,0,256,256,hdcOffscreen,0,0);
  433.   }
  434.  
  435.     return TRUE;
  436. }
  437.  
  438. /*----------------------------------------------------------------------------*\
  439. |   AppWndProc( hwnd, uiMessage, wParam, lParam )                              |
  440. |                                                                              |
  441. |   Description:                                                               |
  442. |       The window proc for the app's main (tiled) window.  This processes all |
  443. |       of the parent window's messages.                                       |
  444. |                                                                              |
  445. \*----------------------------------------------------------------------------*/
  446.  
  447. LONG FAR PASCAL _export AppWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
  448. {
  449.     PAINTSTRUCT ps;
  450.     HDC hdc;
  451.     BOOL f;
  452.     static int CurtainY = 0;
  453.  
  454.  
  455.     switch (msg)
  456.     {
  457.       case WM_CREATE:
  458.         break;
  459.  
  460.       case WM_ACTIVATEAPP:
  461.         fAppActive = (BOOL)wParam;
  462.  
  463.         //*** Remap the system colors and deal with the palette
  464.         if (fIncludeStatic == 0)
  465.         {
  466.           AppActivate(fAppActive);
  467.  
  468.           if (hpalApp)
  469.           {
  470.             hdc = GetDC(hwnd);
  471.  
  472.             UnrealizeObject(hpalApp);
  473.             SelectPalette(hdc, hpalApp, FALSE);
  474.             RealizePalette(hdc);
  475.  
  476.             ReleaseDC(hwnd, hdc);
  477.           }
  478.         }
  479.         break;
  480.  
  481.     case WM_TIMER:
  482.       switch (wParam)
  483.       {
  484.         case 1:
  485.           //*** Animate or terminate the "falling black curtain"
  486.           {
  487.             if (CurtainY < 256)
  488.             {
  489.               DibHorizontalLine(&gInfo.InfoHeader, gpBits, CurtainY, 0);
  490.               CurtainY++;
  491.             }
  492.             else
  493.             {
  494.               CurtainY = 0;
  495.               DibCreateWash(&gInfo.InfoHeader, gpBits);
  496.               KillTimer(hwnd, wParam);
  497.             }
  498.           }
  499.  
  500.           //*** The DIB has changed - redisplay it
  501.           InvalidateRect(hwnd, NULL, FALSE);
  502.           UpdateWindow(hwnd);
  503.  
  504.           break;
  505.  
  506.         case 2:
  507.           //*** Get the current palette
  508.           GetPaletteEntries(hpalApp, 0, 256, aPalette);
  509.           hdc = GetDC(hwnd);
  510.  
  511.           if (fIncludeStatic)
  512.           {
  513.             //*** We'll rotate the middle 236 entries, leaving
  514.             //*** black and white at the top
  515.             aPalette[245] = aPalette[10];
  516.             SelectPalette(hdc, hpalApp, FALSE);
  517.             AnimatePalette(hpalApp, 10, 236, &aPalette[11]);
  518.           }
  519.           else
  520.           {
  521.             //*** We'll rotate the middle 254 entries, leaving
  522.             //*** black and white at the top
  523.             aPalette[255] = aPalette[1];
  524.             SelectPalette(hdc, hpalApp, FALSE);
  525.             AnimatePalette(hpalApp, 1, 254, &aPalette[2]);
  526.           }
  527.  
  528.           ReleaseDC(hwnd, hdc);
  529.  
  530.           InvalidateRect(hwnd, NULL, FALSE);
  531.           UpdateWindow(hwnd);
  532.  
  533.           break;
  534.       }
  535.       break;
  536.  
  537.         case WM_ERASEBKGND:
  538.             break;
  539.  
  540.         case WM_INITMENU:
  541.             break;
  542.  
  543.         case WM_COMMAND:
  544.             return AppCommand(hwnd,msg,wParam,lParam);
  545.  
  546.   case WM_DESTROY:
  547.             PostQuitMessage(0);
  548.             break;
  549.  
  550.         case WM_CLOSE:
  551.           break;
  552.  
  553.         case WM_PALETTECHANGED:
  554.           if ((HWND)wParam == hwnd)
  555.             break;
  556.  
  557.       // fall through to WM_QUERYNEWPALETTE
  558.  
  559.   case WM_QUERYNEWPALETTE:
  560.       hdc = GetDC(hwnd);
  561.  
  562.       if (hpalApp)
  563.         SelectPalette(hdc, hpalApp, FALSE);
  564.  
  565.       f = RealizePalette(hdc);
  566.       ReleaseDC(hwnd,hdc);
  567.  
  568.       if (f)
  569.         InvalidateRect(hwnd,NULL,TRUE);
  570.  
  571.       return f;
  572.  
  573.     case WM_PAINT:
  574.       hdc = BeginPaint(hwnd,&ps);
  575.       if (hpalApp)
  576.       {
  577.         SelectPalette(hdc, hpalApp, FALSE);
  578.         RealizePalette(hdc);
  579.       }
  580.       AppPaint (hwnd,hdc);
  581.       EndPaint(hwnd,&ps);
  582.       return 0L;
  583.     }
  584.     return DefWindowProc(hwnd,msg,wParam,lParam);
  585. }
  586.  
  587. /*----------------------------------------------------------------------------*\
  588. |   AppCommand(hwnd, msg, wParam, lParam )                                     |
  589. |                                                                              |
  590. |   Description:                                                               |
  591. |     Handles WM_COMMAND messages for the main window (hwndApp)                |
  592. |   of the parent window's messages.                                           |
  593. |                                                                              |
  594. \*----------------------------------------------------------------------------*/
  595. LONG AppCommand (HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
  596. {
  597.   HMENU hMenu;
  598.   HPALETTE hPal = GetStockObject(DEFAULT_PALETTE);
  599.   HDC hdc = GetDC(hwnd);
  600.  
  601.     switch(wParam)
  602.     {
  603.         case MENU_ABOUT:
  604.             DialogBox(hInstApp,"AppAbout",hwnd,AppAbout);
  605.             break;
  606.  
  607.         case MENU_EXIT:
  608.             PostMessage(hwnd,WM_CLOSE,0,0L);
  609.             break;
  610.  
  611.     case MENU_RED:
  612.     case MENU_GREEN:
  613.     case MENU_BLUE:
  614.       hMenu = GetMenu(hwndApp);
  615.  
  616.       CheckMenuItem(hMenu, MENU_RED, MF_UNCHECKED);
  617.       CheckMenuItem(hMenu, MENU_GREEN, MF_UNCHECKED);
  618.       CheckMenuItem(hMenu, MENU_BLUE, MF_UNCHECKED);
  619.       CheckMenuItem(hMenu, wParam, MF_CHECKED);
  620.       
  621.       if (wParam == MENU_RED) gWashColor = Red;
  622.       else if (wParam == MENU_GREEN) gWashColor = Green;
  623.       else gWashColor = Blue;
  624.  
  625.       //*** Delete the old palette and create a new one
  626.       hPal = SelectPalette(hdc, hPal, FALSE);
  627.       DeleteObject(hPal);
  628.  
  629.       CreateWashPalette();
  630.  
  631.       InvalidateRect(hwnd, NULL, FALSE);
  632.       UpdateWindow(hwnd);
  633.       break;
  634.  
  635.     case MENU_PALETTE:
  636.       hMenu = GetMenu(hwndApp);
  637.       if (fAnimatePalette)
  638.       {
  639.         fAnimatePalette = 0;
  640.         CheckMenuItem(hMenu, MENU_PALETTE, MF_UNCHECKED);
  641.         KillTimer(hwnd, 2);
  642.       }
  643.       else
  644.       {
  645.         fAnimatePalette = 1;
  646.         CheckMenuItem(hMenu, MENU_PALETTE, MF_CHECKED);
  647.         SetTimer(hwnd, 2, 1, 0);
  648.       }
  649.       break;
  650.  
  651.     case MENU_CURTAIN:
  652.       //*** Just start off the falling curtain
  653.       SetTimer(hwnd, 1, 10, 0);
  654.       break;
  655.  
  656.     case MENU_STATIC:
  657.       hMenu = GetMenu(hwndApp);
  658.  
  659.       if (fIncludeStatic)
  660.       {
  661.         //*** Flag no static color use
  662.         fIncludeStatic = 0;
  663.         CheckMenuItem(hMenu, MENU_STATIC, MF_UNCHECKED);
  664.  
  665.         //*** Remap the system colors
  666.         AppActivate(TRUE);
  667.       }
  668.       else
  669.       {
  670.         //*** Flag static color use
  671.         fIncludeStatic = 1;
  672.         CheckMenuItem(hMenu, MENU_STATIC, MF_CHECKED);
  673.  
  674.         //*** Remap the system colors to normal
  675.         AppActivate(FALSE);
  676.       }
  677.  
  678.       //*** Delete the old palette and create a new one
  679.       hPal = SelectPalette(hdc, hPal, FALSE);
  680.       DeleteObject(hPal);
  681.  
  682.       CreateWashPalette();
  683.  
  684.       InvalidateRect(hwnd, NULL, FALSE);
  685.       UpdateWindow(hwnd);
  686.       break;
  687.     }
  688.  
  689.    ReleaseDC(hwnd, hdc);
  690.  
  691.     return 0L;
  692. }
  693.  
  694. /*----------------------------------------------------------------------------*\
  695. |   ErrMsg - Opens a Message box with a error message in it.  The user can     |
  696. |            select the OK button to continue                                  |
  697. \*----------------------------------------------------------------------------*/
  698. int ErrMsg (LPSTR sz,...)
  699. {
  700.     char ach[128];
  701.  
  702.     wvsprintf (ach,sz,(LPSTR)(&sz+1));   /* Format the string */
  703.     MessageBox(hwndApp,ach,szAppName,MB_OK|MB_ICONEXCLAMATION|MB_TASKMODAL);
  704.     return FALSE;
  705. }
  706.  
  707.  
  708. /***************************************************************************
  709.   Palette Creation
  710.   Create three palettes of solid color washes, with or without statics
  711. */
  712.  
  713. void CreateWashPalette(void)
  714. {
  715.   RGBQUAD aWash[256];
  716.   int i;
  717.  
  718.   //*** Fill in the palette with a 256-color ramp
  719.   for (i=0; i<256; ++i)
  720.   {
  721.     aWash[i].rgbRed = aWash[i].rgbBlue = aWash[i].rgbGreen = 0;
  722.  
  723.     switch (gWashColor)
  724.     {
  725.       case Red:
  726.         aWash[i].rgbRed = i;
  727.         break;
  728.  
  729.       case Green:
  730.         aWash[i].rgbGreen = i;
  731.         break;
  732.  
  733.       case Blue:
  734.         aWash[i].rgbBlue = i;
  735.         break;
  736.     }
  737.  
  738.     aWash[i].rgbReserved = 0;
  739.   }
  740.  
  741.   //*** Turn the wash into a palette
  742.   if (hpalApp)
  743.     DeleteObject(hpalApp);
  744.   hpalApp = CreateIdentityPalette(aWash, 256);
  745. }
  746.  
  747. /***************************************************************************
  748.   Dib drawing routines
  749.  
  750.   One creates a wash of color from left to right,
  751.   the other draws a horizontal line at a given Y in the DIB
  752. */
  753.  
  754. void DibCreateWash(BITMAPINFOHEADER far *Info, void far *pBits)
  755. {
  756.   unsigned int dxBytes = DibWidthBytes(Info);
  757.   int dxWidth = DibWidth(Info);
  758.   int dyLines = (int)Info->biHeight;
  759.   int i, j;
  760.   char unsigned huge *pScanline = (char unsigned huge *)pBits;
  761.   char unsigned huge *pPixel;
  762.  
  763.   if (dyLines < 0)
  764.   {
  765.     dyLines = -dyLines;
  766.   }
  767.  
  768.   for (i=0; i<dyLines; ++i)
  769.   {
  770.     //*** Point to the beginning of this scan line in the DIB
  771.     pPixel = pScanline;
  772.  
  773.     //*** Step through this scan line and fill it
  774.     //*** Wash up on the evens, then down on the odds
  775.     for (j=0; j<256; j+=2)
  776.     {
  777.       *pPixel = (char unsigned)(j % 256);
  778.       pPixel++;
  779.     }
  780.     for (j=253; j>0; j-=2)
  781.     {
  782.       *pPixel = (char unsigned)(j % 256);
  783.       pPixel++;
  784.     }
  785.     //*** Make the last column white
  786.     *pPixel = 255;
  787.  
  788.     //*** Move pointer to the next scan line
  789.     pScanline += dxBytes;
  790.   }
  791. }
  792.  
  793. void DibHorizontalLine(BITMAPINFOHEADER far *Info, void far *pBits,
  794.   int y, char unsigned color)
  795. {
  796.   unsigned int dxBytes = DibWidthBytes(Info);
  797.   char unsigned huge *pPixel;
  798.   int dxWidth = DibWidth(Info);
  799.   int dyLines = (int)Info->biHeight;
  800.   int i;
  801.  
  802.   //*** Account for top-down and bottom-up DIBs
  803.   if (dyLines > 0)
  804.   {
  805.     pPixel = (char unsigned huge *)pBits +
  806.       (long)(dyLines - 1 - y) * (long)dxBytes;
  807.   }
  808.   else
  809.   {
  810.     pPixel = (char unsigned huge *)pBits +
  811.       (long)y * (long)dxBytes;
  812.   }
  813.  
  814.   for (i=0; i<dxWidth; ++i)
  815.   {
  816.     *pPixel = color;
  817.     pPixel++;
  818.   }
  819. }
  820.  
  821.  
  822. //*** Creating an identity palette code here
  823.  
  824. HPALETTE CreateIdentityPalette(RGBQUAD aRGB[], int nColors)
  825. {
  826.   int i;
  827.   struct
  828.   {
  829.     WORD Version;
  830.     WORD NumberOfEntries;
  831.     PALETTEENTRY aEntries[256];
  832.   } Palette =
  833.   {
  834.     0x300,
  835.     256
  836.   };
  837.   HDC hdc = GetDC(NULL);
  838.  
  839.   //*** For SYSPAL_NOSTATIC, just copy the color table into
  840.   //*** a PALETTEENTRY array and replace the first and last entries
  841.   //*** with black and white
  842.   if (GetSystemPaletteUse(hdc) == SYSPAL_NOSTATIC)
  843.   {
  844.     //*** Fill in the palette with the given values, marking each
  845.     //*** as PC_RESERVED
  846.     for(i = 0; i < nColors; i++)
  847.     {
  848.       Palette.aEntries[i].peRed = aRGB[i].rgbRed;
  849.       Palette.aEntries[i].peGreen = aRGB[i].rgbGreen;
  850.       Palette.aEntries[i].peBlue = aRGB[i].rgbBlue;
  851.       Palette.aEntries[i].peFlags = PC_RESERVED;
  852.     }
  853.  
  854.     //*** Mark any remaining entries PC_RESERVED
  855.     for (; i < 256; ++i)
  856.     {
  857.       Palette.aEntries[i].peFlags = PC_RESERVED;
  858.     }
  859.  
  860.     //*** Make sure the last entry is white
  861.     //*** This may replace an entry in the array!
  862.     Palette.aEntries[255].peRed = 255;
  863.     Palette.aEntries[255].peGreen = 255;
  864.     Palette.aEntries[255].peBlue = 255;
  865.     Palette.aEntries[255].peFlags = 0;
  866.  
  867.     //*** And the first is black
  868.     //*** This may replace an entry in the array!
  869.     Palette.aEntries[0].peRed = 0;
  870.     Palette.aEntries[0].peGreen = 0;
  871.     Palette.aEntries[0].peBlue = 0;
  872.     Palette.aEntries[0].peFlags = 0;
  873.   }
  874.   else
  875.   //*** For SYSPAL_STATIC, get the twenty static colors into
  876.   //*** the array, then fill in the empty spaces with the
  877.   //*** given color table
  878.   {
  879.     int nStaticColors;
  880.     int nUsableColors;
  881.  
  882.     //*** Get the static colors
  883.     nStaticColors = GetDeviceCaps(hdc, NUMCOLORS);
  884.     GetSystemPaletteEntries(hdc, 0, 256, Palette.aEntries);
  885.  
  886.     //*** Set the peFlags of the lower static colors to zero
  887.     nStaticColors = nStaticColors / 2;
  888.     for (i=0; i<nStaticColors; i++)
  889.       Palette.aEntries[i].peFlags = 0;
  890.  
  891.     //*** Fill in the entries from the given color table
  892.     nUsableColors = nColors - nStaticColors;
  893.     for (; i<nUsableColors; i++)
  894.     {
  895.       Palette.aEntries[i].peRed = aRGB[i].rgbRed;
  896.       Palette.aEntries[i].peGreen = aRGB[i].rgbGreen;
  897.       Palette.aEntries[i].peBlue = aRGB[i].rgbBlue;
  898.       Palette.aEntries[i].peFlags = PC_RESERVED;
  899.     }
  900.  
  901.     //*** Mark any empty entries as PC_RESERVED
  902.     for (; i<256 - nStaticColors; i++)
  903.       Palette.aEntries[i].peFlags = PC_RESERVED;
  904.  
  905.     //*** Set the peFlags of the upper static colors to zero
  906.     for (i = 256 - nStaticColors; i<256; i++)
  907.       Palette.aEntries[i].peFlags = 0;
  908.   }
  909.  
  910.   ReleaseDC(NULL, hdc);
  911.  
  912.   //*** Create the palette
  913.   return CreatePalette((LOGPALETTE *)&Palette);
  914. }
  915.  
  916.  
  917. //*** AppActivate sets the system palette use and
  918. //*** remaps the system colors accordingly.
  919. void AppActivate(BOOL fActive)
  920. {
  921.   HDC hdc;
  922.   int i;
  923.  
  924.   //*** Just use the screen DC
  925.   hdc = GetDC(NULL);
  926.  
  927.   //*** If the app is activating, save the current color mapping
  928.   //*** and switch to SYSPAL_NOSTATIC
  929.   if (fActive && GetSystemPaletteUse(hdc) == SYSPAL_STATIC)
  930.  
  931.   {
  932.     //*** Store the current mapping
  933.     for (i=0; i<NumSysColors; i++)
  934.       OldColors[i] = GetSysColor(SysPalIndex[i]);
  935.  
  936.     //*** Switch to SYSPAL_NOSTATIC and remap the colors
  937.     SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC);
  938.     SetSysColors(NumSysColors, SysPalIndex, MonoColors);
  939.   }
  940.   else if (!fActive)
  941.   {
  942.     //*** Always switch back to SYSPAL_STATIC and the old mapping
  943.     SetSystemPaletteUse(hdc, SYSPAL_STATIC);
  944.  
  945.     SetSysColors(NumSysColors, SysPalIndex, OldColors);
  946.   }
  947.  
  948.   //*** Be sure to release the DC!
  949.   ReleaseDC(NULL,hdc);
  950. }
  951.  
  952.  
  953. //*** Creating an offscreen buffer (WinGCreateBitmap)
  954.  
  955. HBITMAP ghBitmapMonochrome = 0;
  956.  
  957. HDC Create100x100WinGDC(void)
  958. {
  959.   HDC hWinGDC;
  960.   HBITMAP hBitmapNew;
  961.   struct {
  962.     BITMAPINFOHEADER InfoHeader;
  963.     RGBQUAD ColorTable[256];
  964.   } Info;
  965.   void far *pSurfaceBits;
  966.  
  967.   // Set up an optimal bitmap
  968.   if (WinGRecommendDIBFormat((BITMAPINFO far *)&Info) == FALSE)
  969.     return 0;
  970.  
  971.   // Set the width and height of the DIB but preserve the
  972.   // sign of biHeight in case top-down DIBs are faster
  973.  
  974.   // NOTE: Changed 100 to 256 for my purposes...
  975.   Info.InfoHeader.biHeight *= 256;
  976.  
  977.   Info.InfoHeader.biWidth = 256;
  978.  
  979.   // Create a WinGDC and Bitmap, then select away
  980.   hWinGDC = WinGCreateDC();
  981.  
  982.   if (hWinGDC)
  983.   {
  984.     hBitmapNew = WinGCreateBitmap(hWinGDC,
  985.       (BITMAPINFO far *)&Info, &pSurfaceBits);
  986.     if (hBitmapNew)
  987.     {
  988.       ghBitmapMonochrome = (HBITMAP)SelectObject(hWinGDC,
  989.         hBitmapNew);
  990.     }
  991.     else
  992.     {
  993.       DeleteDC(hWinGDC);
  994.       hWinGDC = 0;
  995.  
  996.     }
  997.   }
  998.  
  999.   return hWinGDC;
  1000. }
  1001.  
  1002. void Destroy100x100WinGDC(HDC hWinGDC)
  1003. {
  1004.   HBITMAP hBitmapOld;
  1005.  
  1006.   if (hWinGDC && ghBitmapMonochrome)
  1007.   {
  1008.     // Select the stock 1x1 monochrome bitmap back in
  1009.     hBitmapOld = (HBITMAP)SelectObject(hWinGDC,         
  1010.     ghBitmapMonochrome);
  1011.     DeleteObject(hBitmapOld);
  1012.     DeleteDC(hWinGDC);
  1013.   }
  1014. }
  1015.  
  1016.  
  1017.